import { cloneDeep, uniqueId } from 'lodash-es'
import sortable from 'sortablejs'
import { ProTableColumns } from '../type'

type Props = {
  tableTitle?: string
  isExport: boolean
  defaultIndexColume: boolean
  indexColumeWidth: number | string
  tableTools: boolean
  isRefresh: boolean
  columns: ProTableColumns
  scrollX?: string | number
  isFullscreen: boolean
}

type Emits = {
  (e: 'update:scrollX', scrollX: string | number | undefined): void
  (e: 'handleColumns', columns: any): void
  (e: 'fullScreenChange'): void
  (e: 'refresh'): void
  (e: 'export'): void
}

export function useTableOperation(props: Props, emits: Emits) {
  const scrollX = props.scrollX

  const indexColumn = {
    type: 'index',
    title: '序号',
    key: '_index',
    width: props.indexColumeWidth
  }

  // 初始化columns，默认设置index列、默认隐藏visiable=false的列
  const columns = computed(() => {
    const columnsData = cloneDeep(props.columns as any) || []

    // 是否配置项中存在index列
    const indexColumnIndex = columnsData.findIndex(
      (col) => col.type === 'index'
    )

    // index列要插在selection列的后面
    if (props.defaultIndexColume && indexColumnIndex === -1) {
      const selectColumnIndex = columnsData.findIndex(
        (col) => col.type === 'selection'
      )
      if (selectColumnIndex !== -1) {
        columnsData.splice(selectColumnIndex + 1, 0, indexColumn)
      } else {
        columnsData.unshift(indexColumn)
      }
    }

    return columnsData.filter((item) => {
      // 没有设置key的列给一个随机的id
      if (!item.key) {
        item.key = uniqueId()
      }
      // 过滤要隐藏的列
      return item.visiable !== false
    })
  })
  const columnsSortList = ref<any[]>([])
  const columnSelectList = ref<any[]>([])
  const columnsSetting = reactive({
    displayColumn: true,
    numberColumn: true
  })

  const setInitValue = () => {
    columnsSortList.value = cloneDeep(columns.value)
    columnSelectList.value = columns.value?.map((v) => v.key)
    columnsSetting.displayColumn = true
    columnsSetting.numberColumn = columns.value.some(
      (col) => col.type === 'index'
    )
  }

  watch(
    columns,
    () => {
      setInitValue()
    },
    {
      immediate: true
    }
  )

  const columnValueList = computed(() => {
    return columnsSortList.value?.filter((col) => {
      return (
        columnSelectList.value.includes(col.key) || col.type === 'selection'
      )
    })
  })

  /**
   * 操作
   */
  const columnSelectListChange = (selectValue: string[]) => {
    columnSelectList.value = selectValue
    columnsSetting.displayColumn = selectValue.length === columns.value.length
  }

  const columnsSortChange = (newIndex, oldIndex) => {
    const sortData = columnsSortList.value
    const temp = sortData[newIndex]
    sortData[newIndex] = sortData[oldIndex]
    sortData[oldIndex] = temp
    columnsSortList.value = sortData
  }

  const displayColumnChange = (checked: boolean) => {
    columnsSetting.displayColumn = checked
    if (checked) {
      columnSelectList.value = columnsSortList.value?.map((v) => v.key)
    } else {
      columnSelectList.value = []
    }
  }

  const numberColumnChange = (checked: boolean) => {
    columnsSetting.numberColumn = checked
    if (checked) {
      const numberColumn =
        columns.value.find((col) => col.type === 'index') || indexColumn
      const selectColumnIndex = columnsSortList.value.findIndex(
        (col) => col.type === 'selection'
      )
      if (selectColumnIndex !== -1) {
        columnsSortList.value.splice(selectColumnIndex + 1, 0, numberColumn)
      } else {
        columnsSortList.value.unshift(numberColumn)
      }
    } else {
      const indexColumnIndex = columns.value.findIndex(
        (col) => col.type === 'index'
      )
      columnsSortList.value.splice(indexColumnIndex, 1)
    }
  }

  const handleFixed = (index, dir) => {
    if (columnsSortList.value[index].fixed === dir) {
      columnsSortList.value[index].fixed = null
    } else {
      columnsSortList.value[index].fixed = dir
    }
  }

  const resetColumns = () => {
    setInitValue()
  }

  const columnSelectListRef = ref<HTMLDivElement>()
  const sortableOptions = {
    animation: 150,
    onEnd: function (evt) {
      const { newIndex, oldIndex } = evt
      columnsSortChange(newIndex, oldIndex)
    }
  }

  const columnIndeterminate = computed(() => {
    return (
      !columnsSetting.displayColumn &&
      !!columnSelectList.value.length &&
      columnSelectList.value.length !== columns.value.length
    )
  })

  watchEffect(() => {
    if (columnSelectListRef?.value) {
      sortable.create(columnSelectListRef?.value, sortableOptions)
    }
  })

  watchEffect(() => {
    if (columnValueList.value.some((item) => item.fixed)) {
      emits('update:scrollX', 1920)
    } else {
      emits('update:scrollX', scrollX)
    }
  })

  watchEffect(() => {
    emits('handleColumns', columnValueList.value)
  })

  const handleRefresh = () => {
    emits('refresh')
  }

  const handleExport = () => {
    emits('export')
  }

  return {
    columns: columnValueList,
    columnsSetting,
    columnSelectList,
    columnsSortList,
    columnIndeterminate,
    columnSelectListRef,
    displayColumnChange,
    numberColumnChange,
    resetColumns,
    columnSelectListChange,
    handleFixed,
    handleRefresh,
    handleExport
  }
}
